package com.Database;

import java.io.InputStream;
import java.util.Scanner;

import com.Core.DatabaseSQL;
import com.Core.GameEngine;
import com.DataWrapper.MapData;
import com.DataWrapper.Profile;

import com.Object.SeaObject;
import com.Triocean.R;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DbHelper extends SQLiteOpenHelper
{	public DbHelper(Context context, String name, CursorFactory factory, int version)
	{	super(context, name, factory, version);
	}
	@Override
	public void onCreate(SQLiteDatabase db)
	{	db.execSQL(DatabaseSQL.createMapTypesTable);
		db.execSQL(DatabaseSQL.createMapsTable);
		db.execSQL(DatabaseSQL.createProfilesTable);
		
		PrepareDatabase(db);
	}
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
	{	
	}
	private void CreateMapTypes(SQLiteDatabase db)
	{	InputStream inp = GameEngine.globalContext.getResources().openRawResource(R.raw.maptypes);
		Scanner in = new Scanner(inp);
		
		while (in.hasNext())
		{	int id = in.nextInt();
			String name = in.next().replace('_', ' ');
			db.execSQL(String.format(DatabaseSQL.addMapType, id, name));
		}
	}
	private void CreateMaps(SQLiteDatabase db)
	{	InputStream inp = GameEngine.globalContext.getResources().openRawResource(R.raw.maps);
		Scanner in = new Scanner(inp);
		
		while (in.hasNext())
		{	int mapTypeId=in.nextInt(), mapLv=in.nextInt();
			String name=in.next();
			
			StringBuilder objects = new StringBuilder();
			int nObj=in.nextInt();objects.append(nObj);
			for (int i=1;i<=nObj;i++)
			{	objects.append(" ");
				objects.append(in.nextInt());
				objects.append(" ");
				objects.append(in.nextInt());
			}
			
			StringBuilder data = new StringBuilder();
			for (int i=1;i<=GameEngine.MAP_SIZE;i++)
				for (int j=1;j<=GameEngine.MAP_SIZE;j++)
				{	data.append(in.nextInt());
					data.append(" ");
				}
			
			StringBuilder goals = new StringBuilder();
			goals.append(in.nextInt());goals.append(" ");
			int nObjGoal = in.nextInt();goals.append(nObjGoal);
			for (int j=1;j<=nObjGoal;j++)
			{	goals.append(" ");goals.append(in.nextInt());
				goals.append(" ");goals.append(in.nextInt());
			}
			
			db.execSQL(String.format(DatabaseSQL.addMap, mapTypeId, mapLv, name, data, objects, goals, GameEngine.MAP_UNAVAILABLE, data));
		}
	}
	private void CreateProfile(SQLiteDatabase db)
	{	Cursor row=db.rawQuery(String.format(DatabaseSQL.getMapByTypeLv, GameEngine.INIT_MAP_TYPE, GameEngine.INIT_MAP_LV), null);
		row.moveToFirst();
		
		db.execSQL(String.format
		(	DatabaseSQL.createProfile,
			GameEngine.INIT_SCORE, GameEngine.INIT_STEPS, GameEngine.INIT_COINS, row.getInt(0)
		));
		row.close();
	}
	public void PrepareDatabase(SQLiteDatabase db)
	{	CreateMapTypes(db);
		CreateMaps(db);
		CreateProfile(db);
	}
	public MapData GetMapByID(int mapID)
	{	Cursor row=getReadableDatabase().rawQuery(String.format(DatabaseSQL.getMapByID, mapID), null);
		row.moveToFirst();
		int typeId, mapLv, status;
		String name, data, objects, goals;
		
		if (row.getCount()==0) return null;
		
		typeId		=	row.getInt(0);
		mapLv		=	row.getInt(1);
		name		=	row.getString(2);
		data		=	row.getString(3);
		objects		=	row.getString(4);
		goals		=	row.getString(5);
		status		=	row.getInt(6);
		
		row.close();
		return new MapData(mapID,typeId,mapLv,name,data,objects,goals,status);
	}
	public MapData GetMapByTypeLv(int mapType, int mapLv)
	{	Cursor row=getReadableDatabase().rawQuery(String.format(DatabaseSQL.getMapByTypeLv, mapType, mapLv), null);
		row.moveToFirst();
	
		if (row.getCount()==0)
		{	row.close();
			return null;
		}
		else
		{	int rs=row.getInt(0);
			row.close();
			return GetMapByID(rs);
		}
	}
	public MapData NextMap(int mapType, int mapLv)
	{	MapData nextMap = GetMapByTypeLv(mapType, mapLv+1);
		if (nextMap==null) nextMap=GetMapByTypeLv(mapType+1, 1);
		return nextMap;
	}
	public MapData[] GetAllMaps()
	{	Cursor row=getReadableDatabase().rawQuery(String.format(DatabaseSQL.getAllMaps), null);
		row.moveToFirst();
		int id, typeId, mapLv, status;
		String name, data, objects, goals;
		
		if (row.getCount()==0) return null;
		else
		{	MapData[] rs = new MapData[row.getCount()]; 
			for (int i=0;i<rs.length;i++)
			{	typeId		=	row.getInt(0);
				mapLv		=	row.getInt(1);
				name		=	row.getString(2);
				data		=	row.getString(3);
				objects		=	row.getString(4);
				goals		=	row.getString(5);
				status		=	row.getInt(6);
				id			=	row.getInt(7);
				rs[i]=new MapData(id,typeId, mapLv, name, data, objects, goals, status);
			}
			return rs;
		}
		
	}
	public Profile GetProfile()
	{	Cursor row=getReadableDatabase().rawQuery(String.format(DatabaseSQL.getProfile), null);
		row.moveToFirst();
		int id,score,steps,coin,curMapId;
		
		id			=	row.getInt(0);
		score		=	row.getInt(1);
		steps		=	row.getInt(2);
		coin		=	row.getInt(3);
		curMapId	=	row.getInt(4);
		
		row.close();
		return new Profile(id, score, steps, coin, curMapId);
	}
	public void UpdateProfile()
	{	Profile pf=GameEngine.profile;
		getWritableDatabase().execSQL(String.format(DatabaseSQL.updateProfile,pf.getScore(),pf.getCurMapId(),pf.getId()));
	}
	public void UpdateMapData()
	{	int[] Map=new int[GameEngine.MAP_SIZE*GameEngine.MAP_SIZE];
		String rs="";
		
		for (int i=0;i<GameEngine.MAP_SIZE;i++)
		{	int base = GameEngine.MAP_SIZE*(GameEngine.MAP_SIZE-1)+i;
			for (int j=0;j<GameEngine.MAP_SIZE;j++)
				Map[base-GameEngine.MAP_SIZE*j]=SeaObject.convertObjTypeToId(GameEngine.mapModel.Get(i, j).getType());
		}
		for (int i=0;i<Map.length;i++)
			if (i!=0) rs=rs+" "+Map[i];
			else rs=rs+Map[i];
		
		getWritableDatabase().execSQL(String.format(DatabaseSQL.updateMaps,rs,GameEngine.profile.getCurMapId()));
	}
	public void ResetMapdata()
	{	getWritableDatabase().execSQL(String.format(DatabaseSQL.updateMaps,GetInitMapData(),GameEngine.profile.getCurMapId()));
	}
	public String GetInitMapData()
	{	return getReadableDatabase().rawQuery(String.format(DatabaseSQL.getInitMapData, GameEngine.profile.getCurMapId()), null).getString(0);
	}
}
